// AnimateList.cpp : implementation file
//

#include "stdafx.h"
#include "ansieditor.h"
#include "AnimateList.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CAnimateList

IMPLEMENT_DYNCREATE(CAnimateList, CView)

CAnimateList::CAnimateList()
{
	m_nInsertMarkPos = -1;//-1;
	m_arrSelectedPage.Add(0);
	m_bUpdatingScrollBar = FALSE;
	GetAppContext()->m_pAnimateList = this;
}

CAnimateList::~CAnimateList()
{
}


BEGIN_MESSAGE_MAP(CAnimateList, CView)
	//{{AFX_MSG_MAP(CAnimateList)
	ON_WM_SIZE()
	ON_WM_LBUTTONDOWN()
	ON_WM_MOUSEMOVE()
	ON_WM_MOUSEWHEEL()
	ON_WM_LBUTTONUP()
	ON_WM_RBUTTONDOWN()
	ON_WM_RBUTTONUP()
	ON_WM_ERASEBKGND()
	ON_WM_MOUSEACTIVATE()
	ON_WM_NCMOUSEMOVE()
	ON_WM_CREATE()
	ON_WM_VSCROLL()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CAnimateList drawing

void CAnimateList::OnInitialUpdate()
{
	CView::OnInitialUpdate();

	UpdateScrollBar();
}

void CAnimateList::OnDraw(CDC* pDC)
{
	CRect rcClient;
	GetClientRect(rcClient);

	CRect rect;
	pDC->GetClipBox(rect);

	CDC dc;
	dc.CreateCompatibleDC(pDC);
	CBitmap bmp;
	bmp.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
	CBitmap *pOldBmp = dc.SelectObject(&bmp);
	dc.SetWindowOrg(rect.left, rect.top);

	int nStartPage = rect.top / m_nPageHeight;
	int nEndPage = rect.bottom / m_nPageHeight;
	if(nStartPage < 0)
	{
		nStartPage = 0;
	}
	if(nEndPage >= GetAppContext()->m_pDoc->m_nPageCount)
	{
		nEndPage = GetAppContext()->m_pDoc->m_nPageCount - 1;
	}

	dc.FillSolidRect(rect, GetSysColor(COLOR_APPWORKSPACE));
	CBrush brHighlight(RGB(0, 0, 255));
	dc.SelectObject(GetStockObject(NULL_PEN));
	dc.SelectObject(&brHighlight);

	int n, nCount = m_arrSelectedPage.GetSize();
	for(n = 0; n < nCount; n++)
	{
		int nPage = m_arrSelectedPage.GetAt(n);
		dc.Rectangle(2, nPage * m_nPageHeight + 2, 
					 rcClient.right - 1, (nPage + 1) * m_nPageHeight + 4);
	}

	dc.SelectObject(GetStockObject(NULL_BRUSH));
	CRect rectDraw(5, 5, rcClient.right - 5, 0);

	char bufNum[5];
	dc.SetBkMode(TRANSPARENT);
	CFont fntNum;
	fntNum.CreatePointFont(90, "Tahoma");
	CFont *pOldFont = dc.SelectObject(&fntNum);
	
	for(n = nStartPage; n <= nEndPage; n++)
	{
		rectDraw.top = m_nPageHeight * n + 5;
		rectDraw.bottom = rectDraw.top + m_nPageHeight - 5;
		GetAppContext()->m_pDoc->m_arrPages[n]->Draw(&dc, rectDraw);
		ltoa(n + 1, bufNum, 10);
		dc.SetTextColor(RGB(0, 255, 0));
		dc.DrawText(bufNum, rectDraw, DT_BOTTOM|DT_RIGHT|DT_SINGLELINE);
		ltoa(GetAppContext()->m_pDoc->m_arrPages[n]->m_nTiming, bufNum, 10);
		dc.SetTextColor(RGB(255, 255, 0));
		dc.DrawText(bufNum, rectDraw, DT_BOTTOM|DT_SINGLELINE);
	}
	
//	int nOldRop2 = dc.SetROP2(R2_NOT);

	if(m_nInsertMarkPos != -1)
	{
		int y = m_nInsertMarkPos * m_nPageHeight + 2;
		CRect rect(rcClient.left + 1, y - 1, rcClient.right, y + 2);
		COLORREF color = RGB(210, 210, 210);
		dc.FillSolidRect(rect, color);
		dc.SelectObject(GetStockObject(WHITE_PEN));
		dc.MoveTo(rcClient.left + 1, y);
		dc.LineTo(rcClient.right, y);
		
//		dc.InvertRect(rect);
	}


//	dc.SetROP2(nOldRop2);

	pDC->GetClipBox(rect);
	pDC->BitBlt(rect.left, rect.top, rect.Width(), rect.Height(), &dc, rect.left, rect.top, SRCCOPY);

//	{
//		int y = m_nInsertMarkPos * m_nPageHeight + 3;
//		CRect rect(rcClient.left + 1, y - 1, rcClient.right, y + 1);
//		pDC->FillSolidRect(rect, RGB(255, 255, 255));
//
//	}

	dc.SelectObject(pOldBmp);
	dc.SelectObject(pOldFont);
}

/////////////////////////////////////////////////////////////////////////////
// CAnimateList diagnostics

#ifdef _DEBUG
void CAnimateList::AssertValid() const
{
	CView::AssertValid();
}

void CAnimateList::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CAnimateList message handlers

void CAnimateList::PostNcDestroy() 
{
}

void CAnimateList::UpdateScrollBar(BOOL bUpdate /* = FALSE */)
{
//	if(!::IsWindow(GetSafeHwnd()))
//	{
//		return;
//	}
	m_bUpdatingScrollBar = TRUE;
	CRect rect;
	GetClientRect(rect);
	ASSERT(rect.Width() >= 0);

	m_nPageHeight = (int)(rect.right * MAX_ROW * 2.0 / MAX_COL + 0.5);// * 25 / 60;
	CSize sizeTotal(0, GetAppContext()->m_pDoc->m_nPageCount * m_nPageHeight + 5);
	
	CSize sizeLine(0, m_nPageHeight);
	CSize sizePage(0, rect.Height());
//	SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);
//	if(sizeLine.cy && 0)
//	{
//		sizeTotal.cy = sizeTotal.cy / sizeLine.cy;
//		sizePage.cy = sizePage.cy / sizeLine.cy;
//		sizeLine.cy = 1;
//	}
//	SetScrollSizes(MM_TEXT, sizeTotal, sizePage, sizeLine);
	SCROLLINFO si;
	si.cbSize = sizeof(si);
	si.fMask = SIF_ALL;// SIF_PAGE|SIF_RANGE;
	::GetScrollInfo(GetSafeHwnd(), SB_VERT, &si);
	si.nMin = 0;
	if(m_nPageHeight > 0)
	{
		si.nMax = GetAppContext()->m_pDoc->m_nPageCount - 1;
		si.nPage = rect.bottom / m_nPageHeight;
	}
	else
	{
		si.nMax = -1;
	}
//	si.nPos = 0
	::SetScrollInfo(GetSafeHwnd(), SB_VERT, &si, TRUE);

	if(bUpdate)
	{
		Invalidate(FALSE);
		UpdateWindow();
	}
	m_bUpdatingScrollBar = FALSE;
}

void CAnimateList::OnSize(UINT nType, int cx, int cy) 
{
	CView::OnSize(nType, cx, cy);
	if(!m_bUpdatingScrollBar)
	{
		UpdateScrollBar();
	}
	
}

void CAnimateList::OnLButtonDown(UINT nFlags, CPoint point) 
{
	m_ptDown = point;
	BOOL bCtrlDown = (nFlags & MK_CONTROL);
	BOOL bShiftDown = (nFlags & MK_SHIFT);

	CPoint pt(point);
	CClientDC dc(this);
	OnPrepareDC(&dc);
	dc.DPtoLP(&pt);
	int nPage = pt.y / m_nPageHeight;

	m_nPagePending = -1;
	if(nPage < GetAppContext()->m_pDoc->m_nPageCount)// && nPage != GetAppContext()->m_pDoc->m_nCurPage)
	{
		if(bShiftDown)
		{
			// batch select
			int nPage1 = m_arrSelectedPage.GetAt(m_arrSelectedPage.GetSize() - 1);
			int nPage2 = nPage;
			if(nPage1 > nPage2)
			{
				swap(nPage1, nPage2);
			}
			m_arrSelectedPage.RemoveAll();
			for(int n = nPage1; n <= nPage2; n++)
			{
				m_arrSelectedPage.Add(n);
			}
		}
		else if(bCtrlDown)
		{
			// multi select	
			int nCount = m_arrSelectedPage.GetSize();
//			BOOL bRemoved = FALSE;
			if(nCount == 1)	// single select
			{
				if(nPage != m_arrSelectedPage.GetAt(0))	// not on sinle selected page
				{
					m_arrSelectedPage.Add(nPage);
//					bRemoved = TRUE;
//					m_nPagePending = nPage;
				}
			}
			else // multi selected
			{
				for(int n = 0; n < nCount; n++)
				{
					if(m_arrSelectedPage.GetAt(n) == nPage)
					{
						break;
					}
				}
				if(n == nCount)
				{
					m_arrSelectedPage.Add(nPage);
				}
				else
				{
					m_nPagePending = nPage;	// pend to select
				}
			}
//			else
//			{
//				for(int n = 0; n < nCount; n++)
//				{
//					if(m_arrSelectedPage.GetAt(n) == nPage)
//					{
//						m_arrSelectedPage.RemoveAt(n);
//						bRemoved = TRUE;
//						break;
//					}
//				}
//			}
//
//			if(!bRemoved)
//			{
//				m_arrSelectedPage.Add(nPage);
//			}
		}
		else
		{
			int nCount = m_arrSelectedPage.GetSize();
			for(int n = 0; n < nCount; n++)
			{
				if(m_arrSelectedPage.GetAt(n) == nPage)
				{
					break;
				}
			}
			if(n == nCount)	// click on non selected page
			{
				m_arrSelectedPage.RemoveAll();
				GetAppContext()->m_pDoc->SetActivePage(nPage, TRUE);
				m_arrSelectedPage.Add(nPage);
			}
			else	// pend to select
			{
				m_nPagePending = nPage;
			}
		}
		Invalidate();
		UpdateWindow();
	}

	CView::OnLButtonDown(nFlags, point);
}

void CAnimateList::OnMouseMove(UINT nFlags, CPoint point) 
{
	CView::OnMouseMove(nFlags, point);
	
	BOOL bLeftDowned = (nFlags & VK_LBUTTON);
	if(bLeftDowned && abs(point.y - m_ptDown.y) > 3)
	{
		CPoint pt(m_ptDown);
		CClientDC dc(this);
		OnPrepareDC(&dc);
		dc.DPtoLP(&pt);
		int nPage = pt.y / m_nPageHeight;
		if(nPage < 0 || nPage > GetAppContext()->m_pDoc->m_nPageCount - 1)
		{
			return;
		}
//
//		int nCount = m_arrSelectedPage.GetSize();
//		for(int n = 0; n < nCount; n++)
//		{
//			if(m_arrSelectedPage.GetAt(n) == nPage)
//			{
//				break;
//			}
//		}
//	
//		if(n == nCount)
//		{
//			return;
//		}
//		
		m_nInsertMarkPos = -1;

		// Begin a drag-drop operation involving the selected widget.
		// 
//		HANDLE hData = ::GlobalAlloc(GMEM_MOVEABLE, 1);

		COleDataSource ods;
		ods.CacheGlobalData(CF_ANSIEDITOR, (HGLOBAL)1);//hData);

//		DROPEFFECT de = 
		ods.DoDragDrop(DROPEFFECT_COPY | DROPEFFECT_MOVE);
	}
}

void CAnimateList::OnLButtonUp(UINT nFlags, CPoint point) 
{
//	afxDump << m_nPagePending << "#######\n";
	if(m_nPagePending != -1)
	{

		BOOL bCtrlDown = (nFlags & MK_CONTROL);
		if(bCtrlDown)
		{
//			m_arrSelectedPage.RemoveAll();
	//		GetAppContext()->m_pDoc->SetActivePage(nPage, TRUE);
//			m_arrSelectedPage.Add(m_nPagePending);
			int nCount = m_arrSelectedPage.GetSize();
			for(int n = 0; n < nCount; n++)
			{
				if(m_arrSelectedPage.GetAt(n) == m_nPagePending)
				{
					m_arrSelectedPage.RemoveAt(n);
				}
			}
		}
		else
		{
			m_arrSelectedPage.RemoveAll();
	//		GetAppContext()->m_pDoc->SetActivePage(nPage, TRUE);
			m_arrSelectedPage.Add(m_nPagePending);
			GetAppContext()->m_pDoc->SetActivePage(m_nPagePending);
		}
//		CPoint pt(point);
//		CClientDC dc(this);
//		OnPrepareDC(&dc);
//		dc.DPtoLP(&pt);
//		int nPage = pt.y / m_nPageHeight;
//		if(nPage == m_nPagePending)
//		{

		Invalidate();
		UpdateWindow();
//		}
	}
	
	CView::OnLButtonUp(nFlags, point);
}

BOOL CAnimateList::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt) 
{
	UINT nSBCode;

	SCROLLINFO si;
	si.cbSize = sizeof(SCROLLINFO);
	si.fMask = SIF_PAGE;
	GetScrollInfo(SB_VERT, &si, SIF_PAGE);

	UINT nStep = gpApp->m_options.nScrollStep;
	if(nStep == 0 || nStep > si.nPage)
	{
		nSBCode = (zDelta > 0)? SB_PAGEUP: SB_PAGEDOWN;
		SendMessage(WM_VSCROLL, nSBCode);
	}
	else
	{
		nSBCode = (zDelta > 0)? SB_LINEUP: SB_LINEDOWN;
		for(UINT n = 0; n < nStep; n++)
		{
			SendMessage(WM_VSCROLL, nSBCode);
		}
	}
	return TRUE;
}

void CAnimateList::OnRButtonDown(UINT nFlags, CPoint point) 
{
	CPoint pt(point);
	CClientDC dc(this);
	OnPrepareDC(&dc);
	dc.DPtoLP(&pt);
	int nPage = pt.y / m_nPageHeight;

	int nCount = m_arrSelectedPage.GetSize();
	for(int n = 0; n < nCount; n++)
	{
		if(m_arrSelectedPage.GetAt(n) == nPage)
		{
			break;
		}
	}
	if(nPage < GetAppContext()->m_pDoc->m_nPageCount && n == nCount)
	{
		GetAppContext()->m_pDoc->SetActivePage(nPage, TRUE);
		SetActivePage(nPage);
		Invalidate();
		UpdateWindow();
	}
	
	CView::OnRButtonDown(nFlags, point);
}

void CAnimateList::OnRButtonUp(UINT nFlags, CPoint point) 
{
	CPoint pt(point);
	ClientToScreen(&pt);
	CMenu *pPopup = gpFrame->GetMenu()->GetSubMenu(2);//->GetSubMenu(10);
	pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_HORPOSANIMATION|TPM_VERPOSANIMATION, 
						   pt.x, pt.y, gpFrame);
	CView::OnRButtonUp(nFlags, point);
}

BOOL CAnimateList::PreCreateWindow(CREATESTRUCT& cs) 
{
	static LPTSTR className = NULL;

	if(!CView::PreCreateWindow(cs))
		return FALSE;

	if(className == NULL)
	{
		className = "XList";
		WNDCLASS wndclass;
		::GetClassInfo(AfxGetInstanceHandle(), cs.lpszClass, &wndclass);
		wndclass.lpszClassName = className;
		wndclass.hbrBackground = (HBRUSH)NULL_BRUSH;
		VERIFY(AfxRegisterClass(&wndclass));
	}
	cs.lpszClass = className;
	
	return TRUE;
}

BOOL CAnimateList::OnEraseBkgnd(CDC* pDC) 
{
	return TRUE;//CView::OnEraseBkgnd(pDC);
}

int CAnimateList::OnMouseActivate(CWnd* pDesktopWnd, UINT nHitTest, UINT message) 
{
	if(GetActiveWindow() != gpFrame)
	{
		gpFrame->SetFocus();
	}
	return MA_NOACTIVATE;// CView::OnMouseActivate(pDesktopWnd, nHitTest, message);
}

void CAnimateList::UpdateActivePage()
{
	if(!::IsWindow(GetSafeHwnd()))
	{
		return;
	}

//	if(!IsWindowVisible())
//	{
//		return;
//	}
	int nPage = GetAppContext()->m_pDoc->m_nCurPage;
	CRect rcClient;
	GetClientRect(rcClient);
	CRect rect(0, m_nPageHeight * nPage, rcClient.right, m_nPageHeight * (nPage + 1));
	CClientDC dc(this);
	OnPrepareDC(&dc);
	dc.LPtoDP(rect);
	InvalidateRect(rect, FALSE);
	UpdateWindow();
}

void CAnimateList::OnNcMouseMove(UINT nHitTest, CPoint point) 
{
	CView::OnNcMouseMove(nHitTest, point);
}

void CAnimateList::EnsurePageVisible(int nPage/* = -1*/)
{
//	if(!::IsWindow(GetSafeHwnd()))
//	{
//		return;
//	}

	if(nPage == -1)
	{
		nPage =  GetAppContext()->m_pDoc->m_nCurPage;
	}
	CRect rcClient;
	GetClientRect(rcClient);
	CPoint ptLP(0, m_nPageHeight * nPage);
	CPoint ptDP(ptLP);
	CClientDC dc(this);
	OnPrepareDC(&dc);
	dc.LPtoDP(&ptDP);
	if(ptDP.y < rcClient.top)
	{
		SetScrollPos(SB_VERT, nPage);
//		ScrollToPosition(ptLP);
	}
	else if((ptDP.y + m_nPageHeight) > rcClient.bottom)
	{
//		ptLP.y -= (rcClient.Height() - m_nPageHeight - 5);
//		ScrollToPosition(ptLP);
		SCROLLINFO si;
		si.cbSize = sizeof(si);
		si.fMask = SIF_PAGE|SIF_POS;
		::GetScrollInfo(GetSafeHwnd(), SB_VERT, &si);
		si.nPos = nPage - si.nPage + 1;
		if(si.nPos < 0)
		{
			si.nPos = 0;
		}
		::SetScrollInfo(GetSafeHwnd(), SB_VERT, &si, TRUE);
//		SetScrollPos(SB_VERT, nPage - );
	}
}

int CAnimateList::OnCreate(LPCREATESTRUCT lpCreateStruct) 
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;
	
	m_oleDropTarget.Register(this);
	
	return 0;
}

DROPEFFECT CAnimateList::OnDragEnter(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) 
{
	DROPEFFECT de = CView::OnDragEnter(pDataObject, dwKeyState, point);
	
	if(!pDataObject->IsDataAvailable(CF_ANSIEDITOR))
	{
		return de;
	}

	return (dwKeyState & MK_CONTROL) ?
			DROPEFFECT_COPY : DROPEFFECT_MOVE;
	
}

DROPEFFECT CAnimateList::OnDragOver(COleDataObject* pDataObject, DWORD dwKeyState, CPoint point) 
{
	DROPEFFECT de = CView::OnDragOver(pDataObject, dwKeyState, point);

	if(!pDataObject->IsDataAvailable(CF_ANSIEDITOR))
	{
		return de;
	}
	
	CClientDC dc(this);
	OnPrepareDC(&dc);
	CPoint lpoint(point);
	dc.DPtoLP(&lpoint);

	int nInsertMarkPos = int((lpoint.y * 1.0 / m_nPageHeight) + 0.5);
	if(nInsertMarkPos > GetAppContext()->m_pDoc->m_nPageCount)
	{
		nInsertMarkPos = GetAppContext()->m_pDoc->m_nPageCount;
	}

	if(m_nInsertMarkPos != nInsertMarkPos)
	{
//		int nPage1 = m_arrSelectedPage.GetAt(0);
//		int nPage2 = m_arrSelectedPage.GetAt(m_arrSelectedPage.GetSize() - 1);
//		if(nInsertMarkPos <= nPage1 || nInsertMarkPos
		m_nInsertMarkPos = nInsertMarkPos;
		Invalidate(FALSE);
		UpdateWindow();
	}

	return (dwKeyState & MK_CONTROL) ?
			DROPEFFECT_COPY : DROPEFFECT_MOVE;
}

BOOL CAnimateList::OnDrop(COleDataObject* pDataObject, DROPEFFECT dropEffect, CPoint point) 
{
	if(pDataObject->IsDataAvailable(CF_ANSIEDITOR) && m_nInsertMarkPos != -1)
	{
		SortSelectedPages();
		int n, nCount = m_arrSelectedPage.GetSize();
		CArray< CAnsiPage*, CAnsiPage* > arrPage;

		if(dropEffect == DROPEFFECT_MOVE)
		{
			int nDecCount = 0;
			for(n = 0; n < nCount; n++)
			{
				int nPage = m_arrSelectedPage.GetAt(n);
				arrPage.Add(GetAppContext()->m_pDoc->m_arrPages.GetAt(nPage));
				if(nPage < m_nInsertMarkPos)
				{
					++nDecCount;
				}
			}
			for(n = nCount - 1; n >= 0 ; n--)
			{
				GetAppContext()->m_pDoc->m_arrPages.RemoveAt(m_arrSelectedPage.GetAt(n));
			}
			m_nInsertMarkPos -= nDecCount;
			GetAppContext()->m_pDoc->m_arrPages.InsertAt(m_nInsertMarkPos, &arrPage);
			//
			for(n = 0; n < nCount; n++)
			{
				int nPage = m_arrSelectedPage.GetAt(n);
				if(GetAppContext()->m_pDoc->m_arrPages.GetAt(nPage) != arrPage.GetAt(n))
				{
					break;
				}
			}
			if(n < nCount) // check if really moved
			{
				GetAppContext()->m_pDoc->SetModifiedFlag();
			}
		}
		else if(dropEffect == DROPEFFECT_COPY)
		{
			GetAppContext()->m_pDoc->GetActivePage()->SaveCaret();
			for(n = 0; n < nCount; n++)
			{
				CAnsiPage *pPage = new CAnsiPage();
				*pPage = *GetAppContext()->m_pDoc->m_arrPages.GetAt(m_arrSelectedPage.GetAt(n));
				arrPage.Add(pPage);
			}
			GetAppContext()->m_pDoc->m_nPageCount += nCount;
			GetAppContext()->m_pDoc->m_arrPages.InsertAt(m_nInsertMarkPos, &arrPage);
			for(n = 0; n < nCount; n++)
			{
				int nPage = m_arrSelectedPage.GetAt(n);
				if(nPage == GetAppContext()->m_pDoc->m_nCurPage)
				{
					GetAppContext()->m_pDoc->SetActivePage(m_nInsertMarkPos + n);
					break;
				}
			}
			UpdateScrollBar();
			GetAppContext()->m_pDoc->SetActivePage(m_nInsertMarkPos);
			GetAppContext()->m_pDoc->SetModifiedFlag();
		}

		m_arrSelectedPage.RemoveAll();
		for(n = 0; n < nCount; n++)
		{
			m_arrSelectedPage.Add(m_nInsertMarkPos + n);
		}

		m_nInsertMarkPos = -1;
//		EnsurePageVisible(GetAppContext()->m_pDoc->m_nCurPage);
		Invalidate(FALSE);
		UpdateWindow();
	}
	return CView::OnDrop(pDataObject, dropEffect, point);
}

void CAnimateList::OnDragLeave()
{
	if(m_nInsertMarkPos != -1)
	{
		m_nInsertMarkPos = -1;
		Invalidate(FALSE);
		UpdateWindow();
	}
	
	CView::OnDragLeave();
}

void CAnimateList::SetActivePage(int nPage)
{
	m_arrSelectedPage.RemoveAll();
	m_arrSelectedPage.Add(nPage);
}

void CAnimateList::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	SCROLLINFO si;
	si.cbSize = sizeof(si);
	si.fMask = SIF_ALL;
	GetScrollInfo(SB_VERT, &si);
	int iVertPos = si.nPos;
	
	switch(nSBCode)
	{
	case SB_TOP:
		si.nPos = si.nMin;
		break;
	case SB_BOTTOM:
		si.nPos = si.nMax;
		break;
	case SB_LINEUP:
		si.nPos -= 1;
		break;
	case SB_LINEDOWN:
		si.nPos += 1;
		break;
	case SB_PAGEUP:
		si.nPos -= si.nPage;
		break;
	case SB_PAGEDOWN:
		si.nPos += si.nPage;
		break;
	case SB_THUMBTRACK:
		si.nPos = si.nTrackPos;
		break;
	default:
		break;
	}
	si.fMask = SIF_POS;
	SetScrollInfo(SB_VERT, &si, TRUE);
	GetScrollInfo(SB_VERT, &si);
	if(si.nPos != iVertPos)
	{
		ScrollWindow(0, m_nPageHeight * (iVertPos - si.nPos), NULL, NULL);
	}
}

void CAnimateList::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) 
{
	CPoint ptOrg(0, -GetScrollPos(SB_VERT) * m_nPageHeight);
	pDC->SetViewportOrg(ptOrg);
}

BOOL CAnimateList::OnScroll(UINT nScrollCode, UINT nPos, BOOL bDoScroll) 
{
	static long nLastTick = 0;
	long nTick = GetTickCount();
	if(nTick - nLastTick > 58)
	{
		OnVScroll(HIBYTE(nScrollCode), nPos, NULL);
		if(bDoScroll)
		{
			UpdateWindow();
		}
		nLastTick = nTick;
	}
	return TRUE;// CView::OnScroll(nScrollCode, nPos, bDoScroll);
}

int cdecl compareint(const void *arg1, const void *arg2)
{
	return *((int*)arg1) - *((int*)arg2);
}

void CAnimateList::SortSelectedPages()
{
	qsort(m_arrSelectedPage.GetData(), m_arrSelectedPage.GetSize(), sizeof(int), compareint);
}
